package com.batis.source.builder.xml;

import com.batis.DataSourceFactory;
import com.batis.mapper.MYEnvironment;
import com.batis.source.builder.BaseBuilder;
import com.batis.source.parsing.MYXPathParser;
import com.batis.source.parsing.MYXnode;
import com.batis.source.session.MYConfiguration;

import java.io.Reader;
import java.util.Properties;

/**
 * xml文件配置加载
 * @author isam2016
 * @create 2021-08-26 11:30 AM
 */
public class MYXMLConfigBuilder extends BaseBuilder {
    Boolean parsed = false;
    MYXPathParser parser = null;
    private String environment;

    public MYXMLConfigBuilder(Reader reader, String environment, Properties props ) {
        super(new MYConfiguration());
        this.configuration.setVariables(props);
        this.parsed = false;
        this.parser = new MYXPathParser(reader, true, props);;
    }
    //  获取ndoe 数据
    private void parseConfiguration(MYXnode root){
        // 获取信息
        try {
            // 获取运行环境配置
            environmentsElement(root.evalNode("environments"));
            // 获取mapper 节点
//            mapperElement(root.evalNode("mappers"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //
    public MYConfiguration parse() {
        if (parsed) {
            throw new Error("Each XMLConfigBuilder can only be used once.");
        }
        parsed = true;
        // "/configuration" 选取元素 路径表达式 获取configuration 节点
        parseConfiguration(parser.evalNode("/configuration"));
        return configuration;
    }

    private void environmentsElement(MYXnode context) throws Exception {
        if (context != null) {
            if (environment == null) {
                environment = context.getStringAttribute("default");
            }
            for (MYXnode child : context.getChildren()) {
                String id = child.getStringAttribute("id");
                if (isSpecifiedEnvironment(id)) {
//                    TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
                    DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
                    MYEnvironment.Builder environmentBuilder = new MYEnvironment.Builder(id, dsFactory.getGetDataSource());
                    configuration.setEnvironment(environmentBuilder.build());
                }
            }
        }
    }

    private DataSourceFactory dataSourceElement(MYXnode context) throws Exception {
        if (context != null) {
            String type = context.getStringAttribute("type");
            Properties props = context.getChildrenAsProperties();
//            DataSourceFactory factory = (DataSourceFactory) resolveClass(type).newInstance(); todo 改为了类
            DataSourceFactory factory = new DataSourceFactory();
            factory.setProperties(props);
            return factory;
        }
        throw new Error("Environment declaration requires a DataSourceFactory.");
    }

    private boolean isSpecifiedEnvironment(String id) {
        if (environment == null) {
            throw new Error("No environment specified.");
        } else if (id == null) {
            throw new Error("Environment requires an id attribute.");
        } else if (environment.equals(id)) {
            return true;
        }
        return false;
    }
}
